JavaScript笔记--Cookie与Session
Table of Contents
概述
HTTP 是一种无状态协议, 即, 当客户端发出请求的时候, 无法得知上一次请求的状态. 一旦数据交换完毕, 客户端与服务器的连接就会关闭, 再次交换数据需要建立新的连接.
如, 用户下单, 由于 HTTP 无状态, 服务器并不知道是哪个用户下的单.
于是产生了 Cookie 和 Session. Cookie 在客户端记录信息, 用于确定用户身份, Session 在服务器记录信息, 用于确定用户身份.
网上找到了一张图, 很清楚地解释了 Cookie 和 Session 的作用:
Cookie
可以简单理解为, Cookie 是服务器向客户端颁发的证书, 客户端用这个证书来证明自己的身份. 这样服务器就知道是哪个用户给自己发送了请求.
Session
Session 是另一种记录用户状态的机制, 当客户端访问服务器的时候, 服务器就把客户端的信息通过 Session 记录在服务器上. 与 Cookie 不同, Session 保存在服务器. 保存的方式很多, 内存, 数据库, 文件, 都可以.
为什么有了 Cookie, 还要用 Session? 主要是因为 Cookie 保存在客户端, 数据很有可能被伪造, 所以重要的数据不能保存在 Cookie; 其次, 是因为 Cookie 中数据如果太多, 影响传输效率.
Session 的使用需要依赖于 Session id, 而 Session id 存在于 Cookie 中(在 Express 中默认是 connect.sid 属性), 所以, 可以说 Session 依赖于 Cookie. 但也不绝对, 如果浏览器禁用了 Cookie, 还可以通过其他方式实现 Session, 如在 url 中传递 session_id. 可以把 session_id 看成是客户端的唯一标识. 当请求到来时, 服务器检查 Cookie 中保存的 session_id, 然后通过这个 id 与服务器的 session data 关联起来, 进行数据的保存和修改.
具体来说, 当客户端发送请求到服务器时, 服务器会随机产生一个 1024bit 的字符串, 存在 Cookie 的 connect.sid 属性里. 当下次客户端再发送请求到服务器里时, 附带的 Cookie 中就会有这个字符串, 这样服务器就知道这个用户的身份了, 然后根据这个身份在服务器中取出相应的数据.
signedCookie
其实, 伪造 Cookie 是一件非常难的事, 因为有经验的开发人员, 都不会直接存储 Cookie, 他们会将 Cookie 进行签名(对内容生成摘要), 再存储.
如, 原本的 Cookie 长这样:
{dotcom_user: 'alsotang'}
然后我们设置一个秘密字符串, 根据这个秘密字符串, 对 Cookie 进行签名. 如:
{'dotcom_user.sig': '4850a42e3bc0d39c978770392cbd8dc2923e3d1d'}
现在, 如果浏览器更改了 Cookie 中的信息, 服务器就会发现 hash 校验结果不同.
在 Express 中使用
使用 Cookie
cookie-parser
npm install cookie-parser
使用
例 1
var express = require('express'); // 可以直接使用req.cookies.cname来访问cookie var cookie = require('cookie-parser'); // 创建app对象 var app = express(); app.use(cookie()) // 设置cookie app.get('/setc',function(req,res){ res.cookie('resc', '设置到cookie里的值', { expires: new Date(Date.now() + 900000), httpOnly: true }); res.end('cookies set ok') }) // 取得cookie app.get('/getc',function(req,res){ console.log('取得的cookie:'+req.cookies.resc) res.end('cookies get ok') }) // 在3000端口监听http请求 app.listen(3000);
例 2
var express = require('express'); // 首先引入 cookie-parser 这个模块 var cookieParser = require('cookie-parser'); var app = express(); app.listen(3000); // 使用 cookieParser 中间件,cookieParser(secret, options) // 其中 secret 用来加密 cookie 字符串(下面会提到 signedCookies) // options 传入上面介绍的 cookie 可选参数 app.use(cookieParser()); app.get('/', function (req, res) { // 如果请求中的 cookie 存在 isVisit, 则输出 cookie // 否则,设置 cookie 字段 isVisit, 并设置过期时间为1分钟 if (req.cookies.isVisit) { console.log(req.cookies); res.send("再次欢迎访问"); } else { res.cookie('isVisit', 1, {maxAge: 60 * 1000}); res.send("欢迎第一次访问"); } });
使用 Session
express-session
express-session 中间件默认将 Session 存放到内存, 我们也可以设置使用其他方式存储.
Session 的参数
- name: 设置 Cookie 中保存 Session 的字段名, 默认为 connect.sid
- store: Session 的存储方式, 默认为内存
- secret: 计算 secret 对应的 hash 值, 放在 Cookie 中, 使产生的 signedCookie 防篡改
- cookie: 设置存放 session id 的 Cookie 的相关选项, 默认为 (default: { path: '/', httpOnly: true, secure: false, maxAge: null })
- genid: 产生新 session id 时使用的函数
- rolling: 为每个请求都重新设置 Cookie, 默认为 false
- resave: 即使 session 未修改, 也重新保存 session 值, 默认为 true
例 1
var express = require('express'); // 首先引入 express-session 这个模块 var session = require('express-session'); var app = express(); app.listen(5000); // 按照上面的解释,设置 session 的可选参数 app.use(session({ secret: 'recommand 128 bytes random string', // 建议使用 128 个字符的随机字符串 cookie: { maxAge: 60 * 1000 } })); app.get('/', function (req, res) { // 检查 session 中的 isVisit 字段 // 如果存在则增加一次,否则为 session 设置 isVisit 字段,并初始化为 1。 if(req.session.isVisit) { req.session.isVisit++; res.send('<p>第 ' + req.session.isVisit + '次来此页面</p>'); } else { req.session.isVisit = 1; res.send("欢迎第一次来这里"); console.log(req.session); } });
例 2
// session功能 var session = require('express-session'); // secret是设置在cookie里的sessionkey app.use(session({'secret':'WBLOG'})) // 设置session app.get('/login',function(req,res){ req.session.user = { 'name':req.query.name, 'pass':req.query.pass, 'avatar':req.query.avatar } res.end('session is OK.'); })
使用 mongodb 存储 Session
var MongoStore = require('connect-mongo')(session); app.use(session({ 'secret':'WBLOG', 'store':new MongoStore({ 'db':'esession', 'host': 'localhost', 'port': 27017, 'collection':'sessions',// 存在哪个集合里,默认为sessions 'ttl':10, // session过期时间 'autoRemove': 'native',// mongo2.2+自动移除过期的session,disable为禁用 'autoRemoveInterval': 10, //移除过期session间隔时间,默认为10分钟 'touchAfter': 24 * 3600 //同步session间隔,默认每次请求都会同步到数据库 }) })) // secret是设置在cookie里的sessionkey // store用来指定session存储位置
Generated by Emacs 25.x(Org mode 8.x)
Copyright © 2014 - Pinvon - Powered by EGO